﻿using NBitcoin.DataEncoders;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using NBitcoin.Altcoins.GroestlcoinInternals;
using NBitcoin.Protocol;
using NBitcoin.Crypto;

namespace NBitcoin.Altcoins
{
	public class Groestlcoin : NetworkSetBase
	{
		public class GroestlEncoder : Base58CheckEncoder
		{

			private static readonly GroestlEncoder _Instance = new GroestlEncoder();
			public static GroestlEncoder Instance
			{
				get
				{
					return _Instance;
				}
			}
			private GroestlEncoder()
			{

			}
			protected override byte[] CalculateHash(byte[] bytes, int offset, int length)
			{
				return GroestlHash(bytes, offset, length);
			}
		}

		public static Groestlcoin Instance { get; } = new Groestlcoin();

		public static byte[] GroestlHash(byte[] arr)
		{
			return GroestlHash(arr, 0, arr.Length);
		}

		public static byte[] GroestlHash(byte[] arr, int offset, int length)
		{
			var digest = new Groestl512();
			digest.update(arr, offset, length);
			var h1 = digest.digest();
			digest.reset();
			digest.update(h1, 0, h1.Length);
			return digest.digest();
		}

		public override string CryptoCode => "GRS";

		private Groestlcoin()
		{
		}

		class GroestlcoinConsensusFactory : ConsensusFactory
		{

			private static readonly GroestlcoinConsensusFactory _Instance = new GroestlcoinConsensusFactory();
			public static GroestlcoinConsensusFactory Instance
			{
				get
				{
					return _Instance;
				}
			}
			class GroestlcoinProtocolCapabilities : ProtocolCapabilities
			{

				private static readonly GroestlcoinProtocolCapabilities _Instance = new GroestlcoinProtocolCapabilities();
				public static GroestlcoinProtocolCapabilities Instance
				{
					get
					{
						return _Instance;
					}
				}
				public GroestlcoinProtocolCapabilities()
				{
					PeerTooOld = false;
					SupportCheckSum = true;
					SupportCompactBlocks = true;
					SupportGetBlock = true;
					SupportMempoolQuery = true;
					SupportNodeBloom = true;
					SupportPingPong = true;
					SupportSendHeaders = true;
					SupportTimeAddress = true;
					SupportUserAgent = true;
					SupportWitness = true;
				}

				public override HashStreamBase GetChecksumHashStream(int hintSize)
				{
					return BufferedHashStream.CreateFrom(GroestlHash, hintSize);
				}
				public override HashStreamBase GetChecksumHashStream()
				{
					return BufferedHashStream.CreateFrom(GroestlHash, 300);
				}
			}

			public override BlockHeader CreateBlockHeader()
			{
				return new GroestlcoinBlockHeader();
			}
			public override Block CreateBlock()
			{
				return new GroestlcoinBlock(new GroestlcoinBlockHeader());
			}

			public override Transaction CreateTransaction()
			{
				return new GroestlcoinTransaction();
			}

#pragma warning disable CS0618 // Type or member is obsolete

			public class GroestlcoinTransaction : Transaction
			{
				protected override HashStreamBase CreateHashStream()
				{
					return BufferedHashStream.CreateFrom(Hashes.SHA256, 300);
				}

				public override ConsensusFactory GetConsensusFactory()
				{
					return GroestlcoinConsensusFactory.Instance;
				}

				protected override HashStreamBase CreateSignatureHashStream()
				{
					return BufferedHashStream.CreateFrom(Hashes.SHA256, 150);
				}
			}

			public class GroestlcoinBlockHeader : BlockHeader
			{
				protected override HashStreamBase CreateHashStream()
				{
					return BufferedHashStream.CreateFrom(GroestlHash, 80);
				}
				public override uint256 GetPoWHash()
				{
					var headerBytes = this.ToBytes();
					var h = GroestlHash(headerBytes);
					Array.Resize(ref h, 32);
					return new uint256(h);
				}
			}

			public class GroestlcoinBlock : Block
			{
				public GroestlcoinBlock(GroestlcoinBlockHeader h) : base(h)
				{
				}
				public override ConsensusFactory GetConsensusFactory()
				{
					return Groestlcoin.Instance.Mainnet.Consensus.ConsensusFactory;
				}
			}
#pragma warning restore CS0618 // Type or member is obsolete


			public override ProtocolCapabilities GetProtocolCapabilities(uint protocolVersion)
			{
				return GroestlcoinProtocolCapabilities.Instance;
			}
		}

		class GroestlcoinStringParser : NetworkStringParser
		{

			private static readonly GroestlcoinStringParser _Instance = new GroestlcoinStringParser();
			public static GroestlcoinStringParser Instance
			{
				get
				{
					return _Instance;
				}
			}
			private GroestlcoinStringParser()
			{

			}

			public override Base58CheckEncoder GetBase58CheckEncoder()
			{
				return GroestlEncoder.Instance;
			}
		}

		//Format visual studio
		//{({.*?}), (.*?)}
		//Tuple.Create(new byte[]$1, $2)
		static Tuple<byte[], int>[] pnSeed6_main = {
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc4,0x01,0x47}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8b,0x13,0x83}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x8e,0x29}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x8e,0x31}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x37,0xd0,0x3a}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x37,0xd0,0x3c}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xff,0x33}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0x8a,0xbb}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x55,0x31,0x99}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x55,0x3c,0x28}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x37,0x3a,0xa0}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xcb,0x55,0xb0}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xd3,0x41}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xf2,0x1e}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc4,0x0b,0xbd}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc4,0x0d,0xce}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xec,0x0e,0xe1}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xec,0x0f,0x78}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xba,0x6f}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xbb,0xb5}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0x74,0x1f}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xf1,0xfb,0xcc}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x55,0x09,0xf5}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x55,0x0e,0x40}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xe1,0x54}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0x9e,0xd7}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x3f,0x19,0xed}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x20,0x21,0x35}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0xad,0xc6}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0xbf,0x0b}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3d,0xbe,0x22}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x3f,0x2b,0x60}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0x44,0x83,0x68}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0x44,0x83,0xd2}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x3b,0x10,0x12}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x3b,0x10,0x68}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x65,0x94,0x2d}, 1331),
		Tuple.Create(new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x65,0x64,0x09}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf0,0x63,0x28,0x85,0x08,0x6b,0xc5,0xbd,0x4c,0xa2}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xba,0x93,0xcd,0x10,0xb7,0x88,0xb1,0xea,0x84,0xb6}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x9e,0xe5,0x2a,0xf1,0x6c,0x10,0x50,0x59,0x6e}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2d,0xe0,0x03,0x6a,0xe6,0x0c,0xe6,0x67,0xb7,0xb3}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb0,0x69,0xe4,0x58,0x08,0xf9,0xbb,0x59,0x32,0x05}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x76,0x41,0x15,0x0f,0x7e,0x32,0xd6,0x28,0x7b,0x8f}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x80,0x56,0xde,0xe2,0x50,0x9c,0x77,0xed,0x61}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x18,0x2e,0x4a,0xc5,0xb7,0x9c,0x53,0x30,0x4d,0xb0}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0x0b,0x42,0xd5,0x78,0x2c,0xab,0xe6,0x53,0x5f}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x73,0x9e,0xa7,0xf1,0x80,0xc9,0xb1,0x27,0x4e,0x92}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x0b,0x71,0xd3,0x48,0x05,0xde,0x77,0xe5,0xc9}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x64,0xa9,0xed,0x37,0x56,0x21,0xd7,0x8a,0xd3,0xfb}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0xbb,0xca,0x30,0xd8,0x1e,0x34,0x42,0xd5,0x4f}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6d,0xc3,0xd9,0x1d,0xe0,0x80,0x9e,0xfa,0x00,0x02}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5a,0x04,0x88,0x49,0x47,0x26,0xd4,0x1e,0xfa,0x57}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf5,0x23,0x67,0x1e,0xfe,0xff,0xe7,0x0c,0x5f,0x83}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4b,0x15,0x08,0x8a,0x33,0x3d,0xf2,0x64,0x27,0x22}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x76,0x91,0xf8,0x7b,0xa2,0x8b,0xea,0x65,0x60,0xef}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x90,0x14,0xbd,0x10,0x2f,0x93,0xef,0xcc,0x42,0x97}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x50,0x0f,0x69,0x93,0x78,0x2d,0x88,0x34,0x2d,0x01}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe2,0x5a,0x9e,0x37,0x33,0x40,0x57,0xe6,0xe6,0x3f}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf8,0x4f,0xf7,0x12,0xe3,0xf4,0x8c,0x00,0x6a,0x88}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0xee,0xdc,0x1a,0x0d,0xd2,0xdd,0xb7,0x82,0x5f}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8e,0xa8,0x6b,0x78,0xdb,0x88,0x7d,0xfe,0x90,0xdb}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x9d,0x1a,0x9f,0x79,0xf2,0xf9,0x09,0x16,0xa7}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe5,0x5a,0x2a,0x0a,0x1a,0x3d,0xe0,0x67,0x05,0xbc}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0x6c,0x04,0x16,0xce,0x73,0x83,0xbb,0xa2,0x66}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa4,0x2e,0x50,0x10,0x53,0x8b,0xe1,0x0a,0xb8,0xcc}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0x2c,0x9a,0xd4,0x3a,0x00,0x88,0x90,0xbe,0xd4}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0b,0x03,0x14,0x91,0xea,0x74,0xba,0x18,0xb3,0x6c}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x25,0x55,0x7b,0x41,0x75,0x04,0xef,0xa0,0x86,0x8a}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x22,0x92,0x65,0xf9,0xbe,0x49,0xc5,0x02,0xc3,0x57}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xec,0x88,0x80,0x78,0x6d,0xe0,0xde,0x71,0x5b,0x8d}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x17,0xd4,0xc3,0x4b,0xaa,0x1f,0x2d,0x53,0x61,0xda}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc1,0x9d,0x51,0x7d,0x2b,0x0f,0x91,0x34,0x22,0x5c}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0xf7,0x89,0x70,0xfb,0x27,0x1a,0x11,0xc4,0x6c}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x14,0x8d,0xf1,0xa6,0xab,0x85,0x13,0x76,0xf2,0x13}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc5,0xbe,0x37,0x4d,0x06,0xab,0x8b,0x98,0x32,0x0b}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x00,0x17,0xf3,0xba,0xc2,0xef,0xa9,0xb4,0xf4,0x26}, 1331),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x33,0x69,0x58,0x39,0x98,0x39,0x06,0xea,0x5a,0x16}, 1331)
		};
		static Tuple<byte[], int>[] pnSeed6_test = {
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0x83,0xaa,0xe8,0xef,0x3c,0xfc,0xa8,0x8e,0x60}, 17777),
		Tuple.Create(new byte[]{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf8,0x59,0x6c,0xe0,0x5a,0x28,0x11,0x21,0x7c,0x53}, 17777)
		};

		protected override NetworkBuilder CreateMainnet()
		{
			var builder = new NetworkBuilder();
			builder.SetConsensus(new Consensus()
			{
				SubsidyHalvingInterval = 210000,
				MajorityEnforceBlockUpgrade = 750,
				MajorityRejectBlockOutdated = 950,
				MajorityWindow = 10080,
				BIP34Hash = new uint256("000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"),
				PowLimit = new Target(new uint256("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")),
				PowTargetTimespan = TimeSpan.FromSeconds(14 * 24 * 60 * 60),
				PowTargetSpacing = TimeSpan.FromSeconds(60),
				PowAllowMinDifficultyBlocks = false,
				PowNoRetargeting = false,
				RuleChangeActivationThreshold = 1916,
				MinerConfirmationWindow = 2016,
				CoinbaseMaturity = 120,
				LitecoinWorkCalculation = true,
				ConsensusFactory = GroestlcoinConsensusFactory.Instance,
				SupportTaproot = true,
				SupportSegwit = true
			})
			.SetNetworkStringParser(GroestlcoinStringParser.Instance)
			.SetBase58Bytes(Base58Type.PUBKEY_ADDRESS, new byte[] { 36 })
			.SetBase58Bytes(Base58Type.SCRIPT_ADDRESS, new byte[] { 5 })
			.SetBase58Bytes(Base58Type.SECRET_KEY, new byte[] { 128 })
			.SetBase58Bytes(Base58Type.EXT_PUBLIC_KEY, new byte[] { 0x04, 0x88, 0xB2, 0x1E })
			.SetBase58Bytes(Base58Type.EXT_SECRET_KEY, new byte[] { 0x04, 0x88, 0xAD, 0xE4 })
			.SetBech32(Bech32Type.WITNESS_PUBKEY_ADDRESS, Encoders.Bech32("grs"))
			.SetBech32(Bech32Type.WITNESS_SCRIPT_ADDRESS, Encoders.Bech32("grs"))
			.SetBech32(Bech32Type.TAPROOT_ADDRESS, Encoders.Bech32("grs"))
			.SetMagic(0xd4b4bef9)
			.SetPort(1331)
			.SetRPCPort(1441)
			.SetName("groestl-main")
			.AddAlias("groestl-mainnet")
			.AddAlias("groestlcoin-mainnet")
			.AddAlias("groestlcoin-main")
			.AddDNSSeeds(new[]
			{
				new DNSSeedData("dnsseed1.groestlcoin.org", "dnsseed1.groestlcoin.org"),
				new DNSSeedData("dnsseed2.groestlcoin.org", "dnsseed2.groestlcoin.org"),
				new DNSSeedData("dnsseed3.groestlcoin.org", "dnsseed3.groestlcoin.org"),
				new DNSSeedData("dnsseed4.groestlcoin.org", "dnsseed4.groestlcoin.org"),
			})
			.AddSeeds(ToSeed(pnSeed6_main))
			.SetGenesis("700000000000000000000000000000000000000000000000000000000000000000000000bb2866aaca46c4428ad08b57bc9d1493abaf64724b6c3052a7c8f958df68e93ced3d2b53ffff0f1e835b03000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3a04ffff001d0104325072657373757265206d75737420626520707574206f6e20566c6164696d697220507574696e206f766572204372696d6561ffffffff010000000000000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
			return builder;
		}

		protected override NetworkBuilder CreateTestnet()
		{
			var builder = new NetworkBuilder();
			builder.SetConsensus(new Consensus()
			{
				SubsidyHalvingInterval = 1052100,
				MajorityEnforceBlockUpgrade = 51,
				MajorityRejectBlockOutdated = 75,
				MajorityWindow = 1000,
				PowLimit = new Target(new uint256("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")),
				PowTargetTimespan = TimeSpan.FromSeconds(1.1 * 24 * 60 * 60),
				PowTargetSpacing = TimeSpan.FromSeconds(60),
				PowAllowMinDifficultyBlocks = true,
				PowNoRetargeting = false,
				RuleChangeActivationThreshold = 108,
				MinerConfirmationWindow = 144,
				CoinbaseMaturity = 120,
				LitecoinWorkCalculation = true,
				ConsensusFactory = GroestlcoinConsensusFactory.Instance,
				SupportTaproot = true,
				SupportSegwit = true
			})
			.SetNetworkStringParser(GroestlcoinStringParser.Instance)
			.SetBase58Bytes(Base58Type.PUBKEY_ADDRESS, new byte[] { 111 })
			.SetBase58Bytes(Base58Type.SCRIPT_ADDRESS, new byte[] { 196 })
			.SetBase58Bytes(Base58Type.SECRET_KEY, new byte[] { 239 })
			.SetBase58Bytes(Base58Type.EXT_PUBLIC_KEY, new byte[] { 0x04, 0x35, 0x87, 0xCF })
			.SetBase58Bytes(Base58Type.EXT_SECRET_KEY, new byte[] { 0x04, 0x35, 0x83, 0x94 })
			.SetBech32(Bech32Type.WITNESS_PUBKEY_ADDRESS, Encoders.Bech32("tgrs"))
			.SetBech32(Bech32Type.WITNESS_SCRIPT_ADDRESS, Encoders.Bech32("tgrs"))
			.SetBech32(Bech32Type.TAPROOT_ADDRESS, Encoders.Bech32("tgrs"))
			.SetMagic(0x0709110b)
			.SetPort(17777)
			.SetRPCPort(17766)
			.SetName("groestl-test")
			.AddAlias("groestl-testnet")
			.AddAlias("groestlcoin-test")
			.AddAlias("groestlcoin-testnet")
			.AddDNSSeeds(new[]
			{
				new DNSSeedData("testnet-seed1.groestlcoin.org", "testnet-seed1.groestlcoin.org"),
				new DNSSeedData("testnet-seed2.groestlcoin.org", "testnet-seed2.groestlcoin.org"),
			})
			.AddSeeds(ToSeed(pnSeed6_test))
			.SetGenesis("030000000000000000000000000000000000000000000000000000000000000000000000bb2866aaca46c4428ad08b57bc9d1493abaf64724b6c3052a7c8f958df68e93c02a8d455ffff001e950a64000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3a04ffff001d0104325072657373757265206d75737420626520707574206f6e20566c6164696d697220507574696e206f766572204372696d6561ffffffff010000000000000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
			return builder;
		}

		protected override NetworkBuilder CreateRegtest()
		{
			var builder = new NetworkBuilder();
			builder.SetConsensus(new Consensus()
			{
				SubsidyHalvingInterval = 150,
				MajorityEnforceBlockUpgrade = 51,
				MajorityRejectBlockOutdated = 75,
				MajorityWindow = 144,
				PowLimit = new Target(new uint256("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")),
				PowTargetTimespan = TimeSpan.FromSeconds(1.1 * 24 * 60 * 60),
				PowTargetSpacing = TimeSpan.FromSeconds(60),
				PowAllowMinDifficultyBlocks = true,
				MinimumChainWork = uint256.Zero,
				PowNoRetargeting = true,
				RuleChangeActivationThreshold = 108,
				MinerConfirmationWindow = 144,
				CoinbaseMaturity = 120,
				LitecoinWorkCalculation = true,
				ConsensusFactory = GroestlcoinConsensusFactory.Instance,
				SupportTaproot = true,
				SupportSegwit = true
			})
			.SetNetworkStringParser(GroestlcoinStringParser.Instance)
			.SetBase58Bytes(Base58Type.PUBKEY_ADDRESS, new byte[] { 111 })
			.SetBase58Bytes(Base58Type.SCRIPT_ADDRESS, new byte[] { 196 })
			.SetBase58Bytes(Base58Type.SECRET_KEY, new byte[] { 239 })
			.SetBase58Bytes(Base58Type.EXT_PUBLIC_KEY, new byte[] { 0x04, 0x35, 0x87, 0xCF })
			.SetBase58Bytes(Base58Type.EXT_SECRET_KEY, new byte[] { 0x04, 0x35, 0x83, 0x94 })
			.SetBech32(Bech32Type.WITNESS_PUBKEY_ADDRESS, Encoders.Bech32("grsrt"))
			.SetBech32(Bech32Type.WITNESS_SCRIPT_ADDRESS, Encoders.Bech32("grsrt"))
			.SetBech32(Bech32Type.TAPROOT_ADDRESS, Encoders.Bech32("grsrt"))
			.SetMagic(0xdab5bffa)
			.SetPort(18888)
			.SetRPCPort(18443)
			.SetName("groestl-reg")
			.AddAlias("groestl-regtest")
			.AddAlias("groestlcoin-reg")
			.AddAlias("groestlcoin-regtest")
			.SetGenesis("030000000000000000000000000000000000000000000000000000000000000000000000bb2866aaca46c4428ad08b57bc9d1493abaf64724b6c3052a7c8f958df68e93c02a8d455ffff001e950a64000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3a04ffff001d0104325072657373757265206d75737420626520707574206f6e20566c6164696d697220507574696e206f766572204372696d6561ffffffff010000000000000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
			return builder;
		}

		protected override void PostInit()
		{
			RegisterDefaultCookiePath("Groestlcoin");
		}
	}
}
